All Articles

AWS 비용 연 1억원 줄이기

죄송합니다. 제목은 어그로입니다. 본 경험 공유는 모두에게 해당할 수 없는 내용입니다. 효율적으로 서비스를 운영 중이신 분은 본 페이지를 닫아주세요.

시나리오

운영중인 어트랙트 서비스가 코로나 19의 영향으로 여유가 생겼다. 이 시기가 미뤄왔던 비용 절감 프로젝트의 적기라고 생각되어 진행했다.

잠깐! 비용 절감을 해야 할 때는 언제일까?

비용 절감을 하게 되면, 개발자 한 명 이상이 투입되어야 한다. 즉 비용 절감을 위해 비용을 지불해야 한다는 것이다. 그럼 언제 비용 절감을 하면 좋을까. 이거에 대해 대충 의사 코드를 짜보자.

러프한_예상_절감_비용 = 대충_빠른_파악() // 이 함수가 지연된다면 긴급 종료 검토
만약 "(러프한_예상_절감비용 * 서비스의_최소_수명) - 비용절감에_대한_개발자_투입비용" > 
		  "(개발자가_만드는_부가가치 - 개발자_투입비용) * 개발자가_있는_기간" 
  이라면 비용_절감_진행()
  아니라면 걍_하던_개발이나_하자()

보통의 회사라면 걍_하던_개발이나_하자 함수를 실행하는 게 맞을 것이다. 그렇지 않다면 뭔가 잘못 돌아가고 있진 않은가 의심해봐야 한다. 아니 그러면 화자의 경우는 뭔가 잘못 돌아가고 있었다는 건가? 그렇다 뭔가 잘못되었다. 실제로 서버 비용은 정상적이지 않은 수준으로 높았다.

위에서도 언급했지만, 코로나 19의 영향으로 개발자(나)가_만드는_부가가치가 굉장히 낮아졌다. 또한 기존에 AWS에서 굉장히 낭비가 심한 부분이 많았기 때문에 비용 절감에 집중할 수 있었다. 물론 어트랙트 서비스만으로 비용절감을 크게 한 건 아니고, 회사의 모든 서비스를 전체적으로 묶어서 TF형식으로 진행하였다. (개발자를 그냥 비용으로 보는 것에 대해 거부감을 느끼고 계실 분들도 있을 거라 생각한다. 하지만 그냥 현실에서 발생할 수밖에 없는 문제다.)

어떤 식으로 접근 해야할까?

(현재 지불하고 있는 비용 * 0.8) + (내가 빨리 처리할 수 있는 것 * 0.2) 정도로 설정한 뒤 작업을 진행했다. 비용 파악은 계약을 맺은 AWS 솔루션을 통해서 확인하였다. 이를 통해 비용은 EC2 > Data Transfer > CloudFront > RDS > S3 > ECS > Elastic Cache 순으로 정리가 되었지만, 실제 작업은 RDS > ECS > EC2 > S3 > Data Transfer(CloudFront) > Elastic Cache 순으로 진행했다. 물론 이것도 어느 정도 이런 형태로 진행한 거지 실제 작업은 계속 번갈아 가면서 이루어졌다.

본격적인 비용 절감

RDS

일단 사용하지 않는 DB는 당연히 삭제를 진행하고 대부분의 DB를 통합했다. CPU 사용량 평균을 통해서 흡수 합병을 하는 느낌으로 진행하였다. 기존에는 서비스에 따라 DB가 다 각각 있었는데, 어느 정도 의존성이 있는 녀석들은 묶었다. 문제는 로그 DB와 운영 DB를 통합하는 작업이었다. 애초에 통합되어 있던 DB를 한번 분리했던 녀석인데, 분리한 이유가 부하 분산의 목적이었기 때문에, 다시 통합할 때는 어느 곳에서 부하가 큰 지 다시 한번 살펴 봐야만 했다. 다행히 저번에는 이슈 파악이 정확하게 안되어 급하게 분리하였지만, 분리한 이후 로그관련하여 최적화가 많이 이뤄졌고, 실제로 큰 부하는 오히려 로그 DB와 운영 DB의 데이터 동기화 로직이 부하가 가장 컸기 때문에 바로 새벽에 작업을 진행하였다. 동기화 작업은 양쪽 DB에 모두 부하를 주는 작업이었기 때문에 최종적으로 CPU 사용률을 많이 낮출 수 있었고, 관리 포인트도 줄일 수 있게 되었다. 그 밖에 여러 디비를 통합 및 인스턴스 등급 조정을 통해 비용을 아낄 수 있었다.

RDS 관련하여 추가적인 이야기를 하자면, RI에 대해 좀 더 신중하게 생각하길 권한다. 이전 CTO(이하 전TO)가 RI를 잡아 놓는 바람에 비용이 애매해진 부분이 많았다. RI가 완전 선결제가 아닌 경우 특히 애매해지며, RDS의 RI는 중간에 판매도 불가할 뿐더러 정말로 비용절감이 큰 지 여러번 고민하길 권한다. 아마존에서 새로운 등급의 인스턴스가 나오게 되면 인스턴스의 Modernize도 애매해지고, 최적화로 인해 큰 등급의 인스턴스를 사용을 안하게 될 수도 있다. 이런 이유들로 인해 RI를 사기전에 최적화 할 수 있는 병목등은 없는 지 한번 꼭 확인하고 RI를 결정하길 권한다. 우리 회사 같은 경우 이번에 RI가 만료되는 타이밍과 겹쳐서 비용을 더 절감할 수 있었다.

위와 같은 작업을 통해 RDS에서 비용은 월 최소 1000달러 감소했다. 500달러 추가 감소예정이지만 아직 작업일정을 못정했다.(모든 비용은 최소를 기준으로 잡은 예상값이다. 아직 온전하게 한 달 이상 사용하지 않았고, 트래픽이 월별로 다르기 때문에 완벽하게 정확한 비용은 측정이 불가하다.)

ECS (Fargate)

ECS(Fargate, EC2 기반은 사용하지 않고 Fargate만 사용 중이다.) 비용 감소는 쉬운 편이었다. 어트랙트의 경우 몇몇 배치 서버는 사무실 컴퓨터로 그냥 이전한 것들도 있고, 사용량이 적은 서비스의 경우 stage를 과감하게 삭제하기도 했다. 또한 위에 DB를 통합하면서 로깅서버와 운영서버를 통합하기도 했다. stage 서버 유지비가 들어봤자 얼마나 든다고 생각할 수도 있는데, 다른 서버들은 모르겠지만 tomcat 등 서블릿 기반 서버의 경우 그냥 기본적으로 실행하는 것 자체만으로도 어느 정도 사양의 스펙 이상어야한다. 특히 아직 유저가 하루에 100명도 안 되는 서비스의 경우 stage를 유지할 이유를 잘 못 느꼈기 때문에 삭제를 진행하기로 했다. (장애가 나도 치명적이지 않은 서비스라는 의미다.) 또한 어드민 서버 등과 같이 무중단이 필요 없는 서버의 경우 Spot Fargate로 전환했다. 서비스를 삭제하면서 서비스에 붙은 ALB도 같이 삭제하여 추가적인 절감이 있었다. 이렇게 ECS 쪽에서 월 최소 600달러 감소했다.

EC2

EC2의 경우 말이 EC2지 단순 인스턴스 외에 여러 가지 항목들이 뭉쳐서 요금이 나오기 때문에 할 게 좀 많았다. 일단 인스턴스를 보기 전에 쉽게 날릴 수 있는 것부터 확인했다.

EBS

뭔가 오토스케일링이 잘못 설정되어있던 건지 모르겠지만 쓸데없이 할당되지 않은 EBS가 너무 많았다. 보통 이런 거에 중요한 데이터가 들어있을 수 있으니 날리지 않는다는 생각을 가질 수 있지만, 개인적인 생각으로는 절대 아무도 이 이후에 확인하지 않는다는 생각이 들어서 협의 후 바로 다 삭제에 들어갔다. EBS는 용량을 함부로 크게 잡으면(100GiB 단위 정도) 생각보다 요금폭탄 맞을 확률이 높다. 총 몇 GiB를 삭제 했는지는 잘 모르겠다.

EIP

EIP 역시 할당되지 않은 것들은 그냥 바로 릴리즈해 버렸다. 생각보다 남는 게 많아서 한 150달러는 빠지지 않았을까 싶다.

ELB

생각보다 ELB가 너무 많아서, 이번에 정말 하나하나 확인해가면서 타겟이 설정되어 있지 않은 것과 다른 팀에서 서비스 상태가 아닌 게 의심되는 것들을 골라 상의 후 삭제를 진행했다. ELB는 한 200달러 정도 절감을 예상중이다.

NAT

왜인지 모르겠는데 빌링시스템에서 NAT 비용도 EC2 카테고리로 잡혀있었다. NAT 비용은 NAT 자체의 유지비용은 많이 안나오는 편이었는데, 전TO가(그만 소환하고 싶은데, 작업을 진행하다 보니 사실상 비용 절감 프로젝트의 원흉이었다.) 지시하면서 거의 모든 개발서버가 Private DNS만 갖게되어 불필요하게 NAT가 많고 특히 NAT의 트래픽 비용이 상당했다. 정말 필요한 부분을 제외하고는 NAT를 사용하지 않도록 변경하였다. NAT가 이외의 성과였는데, NAT에서는 최소 예상 절감 비용을 1,000달러 정도로 측정했다.

대부분 서비스에서 NAT로 변경해도 문제가 없었지만, 기존에 Private ENI만 할당된 걸 몇 개 확인 못했다. 효율이 높았지만 담부터는 좀더 꼼꼼하게 확인해야겠다.

Instances

대망의 인스턴스들이었는데, 어트랙트에서는 이제 EC2는 전혀 사용하고 있지 않아서, 타 파트와 상의를 하며 진행했기 때문에 작업을 여러 번 나눠서 진행했다. 아마 다른 회사에서도 이 비용 절감에 대해서 고민이 많을텐데, 개인적으로는 아래와 같은 순서로 접근했다.

  1. 사용하지 않는 인스턴스 삭제
  2. CPU 사용량 대비 인스턴스 타입 조정
  3. 인스턴스 Modernize(세대 교체, ex. t2.medium => t3.mediuml 등의 인스턴스를 현 세대로 바꾸는 작업)
  4. 높은 트래픽의 높은 CPU 사용률을 가진 인스턴스 최적화후 등급 조정
  5. T타입 인스턴스가 아닌 것 중 시간대별 사용량이 차이가 많이 나는 인스턴스에 대해 T타입 인스턴스로 변경

1항목은 너무 당연한 거 아닌가 싶은데, 생각보다 레거시가 많은 서비스에서는 당연한 게 아니었다. 사용하지 않고 있는데 삭제하면 안되나?는 질문에 돌아오는 건 보통 거기에 뭐가 있는 지 몰라서 못 지우겠다. 이기 때문이다. 이때 보통 ‘그렇구나’하고 넘어갈 수가 있는데, 거기에 뭐가 있는 지 모른다는 건 앞으로 문제가 생겨도 그게 문제인지도 모를 것이기 때문에 볼일이 없고, 이게 삭제된다고 문제가 된다면 결국 언젠가 생길 문제가 아닌가요? 라는 논지로 설득하고, 삭제를 진행했다.

2번 항목이 사실 더 당연하다고 생각하는데, 무중단으로 인스턴스 타입이 조정 가능한 경우에는 그렇게 조정하고, 그게 아닐 경우에는 최대한 인스턴스 사용이 적을 때 중단하면서 타입을 중단했다. 이 부분에 대해서도 서비스 무중단에 대해 병적으로 지킬 생각을 가지신 분들이 계시는 데, 중단으로 생길 이슈 처리 비용(기업 기술에 대한 신뢰도 포함, 즉 매우 영향력이 작은 요소)을 다 고려해도, 작업자의 인건비보다 작다면 그냥 중단해가면서 작업을 진행해도 된다고 생각한다. 인스턴스 타입 조정의 경우 T인스턴스의 경우 AWS문서의 Baseline 기준으로 조정했다.

3번 항목은 2번항목과 일부 겹치는 내용도 있는데, t2 인스턴스에서 t3로 변경할 때 보통 한단계씩 등급을 낮출 수 있었다. 일부 오래된 레거시의 경우 예상치 못한 이슈가 발생했다. 그리고 RDS에서도 한번 언급했지만 일부가 RI로 잡혀있어서 애매한 경우도 있었다. 이것도 전 TO의 작품이었는데, EC2 RI의 경우 판매가 가능하여 판매도 고려하고 있다. 아무튼 RI를 고려중이라면 꼭 새로운 세대의 가능성을 염두에 두자.

4번 항목을 진행한 것도 전TO의 작품이었다.. 낮은 트래픽인데 CPU사용률이 높은 건 보통 최적화해도 효과가 크지 않다고 생각했다. 그리고 트래픽이 낮은데 사양이 높은 것들은 거의 없었기 때문에, 높은 트래픽인 녀석을 집중적으로 공략했다. 높은 트래픽을 가진 녀석들일수록 작은 최적화에도 민감하게 반응할 수 있기 때문이다. 코드 중 불필요하게 함수를 두 번 호출하거나, 불필요한 라이브러리 사용으로 성능을 해치는 부분을 좀 개선했는데, 생각보다 엄청나게 큰 차이는 없었지만 전체적으로 20%정도 CPU 사용량이 줄었고, 인스턴스 타입을 조정할 수 있었다.

5번 항목은 이전에 c5만 있고 t3가 없을 때, t2 => c5로 이전한 것들이 많았는데, 이때 이전한 것들을 다시 t3로 바꾸었다. 앞으로는 멈추지 않는 배치 등을 돌리는 게 아니라면 c타입을 잘 사용 안하게 될 것 같다. 특히 unlimited 크레딧 기능이 생각보다 리스크 대비 효율이 좋다고 생각한다.

인스턴스 조정에 따른 비용 절감은 최소 450달러 정도로 예상한다. 생각보다 엄청 큰 비용이 줄어들진 않았다.

S3

S3 비용이 상당히 많이 나오는 편이었는데, 이번에도 전TO를 소환해버린다. 로그가 굉장히 raw하게 S3에 저장이 되고 있었는데, 증가 추세를 보면 매달 70달러정도가 증가하고 있었다. 즉 1년이 지나면 700달러가 넘게 나가고 그런식으로 점점 달마다 서서히 비용이 증가하고 있었다. S3비용 중 네트워크 IO비용이 높다면 데이터를 계속 활용하고 있는 것이기 때문에 큰 문제가 되진 않겠지만 단순 저장 비용이 크다는 건 문제가 있었다. 아래의 명령어를 통해 버킷중 실제 데이터가 큰 부분을 확인하고 작업을 진행했다.

aws s3 ls s3://mybucket --recursive --human-readable --summarize

삭제를 할 때 로그가 나중에 필요할 수도 있다라는 충돌이 있었는데,

  1. 데이터가 너무 크기 때문에 나중에 데이터를 로딩하는 것 자체가 코스트가 너무 크다.
  2. 현재 이 데이터를 정확히 파악하고 있는 사람이 있는가?
  3. 정말 이렇게 큰 데이터가 필요한가?
  4. 우리가 분석 환경을 완성할 때 즈음 이미 다시 충분히 큰 데이터가 쌓일 것이다.

등의 이유로 설득을 하여 1년 이전의 로그는 삭제하고, 나머지 데이터들은 스토리지 클래스를 조정하기로 했다. 6개월~ 12개월은 Deep Glacier, 3~6 은 그냥 Glacier 이런식으로 구간별로 나누어서 진행했다.

S3 비용은 단순히 삭제와 등급조정이었기 때문에 작업코스트가 크지 않은 효율 좋은 작업이었다. 최소 700달러 정도 절감 예상 중이다.

추가적으로 로그가 왜 그렇게 컸는가를 이야기하자면(안봐도 되는 한풀이 입니다.), 트래픽이 기본적으로 크기도 했지만 전TO가 이상한 빅데이터 약을 섭취했던 것 같다. 모든 데이터는 raw하게 모든 지 저장하고 나중에 분석해야 한다면서 분석은 실시간으로 이루어 져야한다라는 이야기만을 계속했다. 그래서 대체 보고 싶은 게 무엇이냐고 물을 때마다 그건 데이터를 저장하고 나서 생각하는 것이다라는 말만 반복했다. 여러분들은 로그 데이터를 분석하려고 한다면, 빅데이터가 중요한 게 아니라 쓸모있는 데이터가 더 중요하고 raw하게 저장한 데이터는 전처리에 더 큰 시간이 걸린다는 것을 꼭 기억하면서 개발하셨으면 좋겠다.

Data Transfer (CloudFront)

Data Transfer는 내 주도로 작업이 많이 이뤄지지는 않았고, 분석 쪽에 집중을 했다. 이게 가장 처리와 측정이 애매한 녀석이었는데, 일단 압축이 안되었거나 정적인 파일 중에 minify가 덜된 부분이 있는 지 확인했다.(공백등이 minify가 안 된 건 대부분 압축에서 걸러지긴 했다.) 그나마 CDN을 통한 데이터는 요금정보를 확인해보면 알겠지만, 일정 수준이 넘어가면 요금 약정이 가능하여 크게 할인이 가능하다. 할인 범위는 대외비로 알고 있어서 정확한 비용은 여기서 밝히는 게 불가하지만 큰폭으로 할인해준다. 그래도 lazy load로 돌릴 수 있는 부분들을 최대한 찾아서 lazyload로 바꿔주었다. 문제는 서버 응답 값이었는데, 이번에 응답값중 불필요하게 설정값을 주거나 비어있는(null, "", undefined 등)은 파싱하기전에 필드를 삭제하여 응답값을 주도록 변경하였다. 몇십, 몇백 KB 줄인다고 큰 차이 있겠나 싶을 수 있지만, 사실 한 달 PV가 10억이 넘어가면 얘기가 달라진다. AWS 데이터 전송 요금표

월 10억 PV라고 가정하고 100킬로바이트를 줄이면 대충 계산했을 때 ( 1,000,000,000(PV) * 100,000(Bytes) ) / ( 1000(kB =>) * 1000(MB =>) * 1000 (GB) ) * 0.126($)하면 1200달러가 된다. 이런걸 생각해보면, 자주 사용하는 정적인 파일들은 최대한 서버가 아닌 CDN을 태우도록 하자.

여기서도 큰 절감이 예상되지만 정확하게 측정이 불가하며 종합적인 이유로 정확한 비용은 공개하기가 애매한 점 양해 부탁드린다.

Elasticache

이미 위 작업들로 인해 절감 폭이 크진 않아서 아직 작업을 진행하고 있진 않은데, 아마 시간이 되면 작업을 진행할 것 같다. Elasticache의 경우 실제로 사용 중인지 아닌지 판단을 어떻게 해야 할 지 애매했는데, Item 개수의 변화량과 캐쉬 히트 수를 가지고 실 사용중인지 판단했다.

후기

7월의 AWS 요금

7월 한달간 요금 그래프이다. Y축을 정확히 공개할 수 없지만 전반적으로 우하향인 걸 알 수 있다. (1일과 말일은 기타요소로 인해 정확하지 않다.)

제목에는 1억이라고 쓰긴 했지만, 환율이랑 부가세 등등 고려하고 명시하지 않은 기타 잡다한 것들을 다 합치면 한 9,000만 좀 넘는 금액이 절감될 것 같다. 결국 서버비라는 건 어차피 나가야 할 돈이기에 줄이는 건 한계가 있다. 줄일 순 있지만 없앨 수 있는 비용은 아니기 때문이다. 또 위 작업들은 컨설턴트랑 계약을 맺었다고 해도 그쪽에서 제안할만한 해결책들은 아니다. 하지만 코드스멜처럼 서버비에서 구린내가 난다면 한번 시간을 들여 절감을 진행하는 것도 나쁘진 않다고 생각한다.

작업을 진행하면서 느낀 점은 절감을 담당하는 사람이 뭔가 작업을 하는 것보다도 절감에 대해 실무자를 설득하는 게 더 어려운 과정이라고 느꼈다. 절감하겠다고 다짐했으면 실무자를 설득시킬 수 있는 논리와 어휘력을 미리 잘 준비해두는 게 중요하단 생각이 들었다.